home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
SGI Hot Mix 17
/
Hot Mix 17.iso
/
HM17_SGI
/
research
/
lib
/
map_patch.pro
< prev
next >
Wrap
Text File
|
1997-07-08
|
9KB
|
224 lines
; $Id: map_patch.pro,v 1.12 1997/03/26 00:15:35 dave Exp $
;
; Copyright (c) 1994-1997, Research Systems, Inc. All rights reserved.
; Unauthorized reproduction prohibited.
function map_reduce_360, a ;Reduce an angle to the range of +- 180.
b = a mod 360.
neg = where(b lt 0, count)
if count gt 0 then b[neg] = b[neg]+360.
return, b
end
FUNCTION map_patch, Image_Orig, Lons, Lats, $
XSTART = xstart, YSTART = ystart, $
XSIZE = xsize, YSIZE = ysize, $
LON0 = lon0, LON1 = lon1, $
LAT0 = lat0, LAT1 = lat1, $
MISSING = missing, MAX_VALUE = max_value, $
TRIANGULATE=triangulate, DEBUG = debug
;+
;NAME:
; map_patch
;PURPOSE:
; This function linearly interpolates a data sampled in
; latitude/longitude into device space. Data values may be
; either rectangularly or irregularly gridded over the globe.
;Category:
; Mapping
;Calling Sequence:
; result = map_patch(Image_Orig [, Lons] [, Lats])
;INPUT:
; Image_Orig- A array containing the data to be overlayed on map.
; It may be either 1D or 2D. If 2D, it has Nx columns,
; and Ny rows. The cell connectivity must be
; rectangular, unless the TRIANGULATE keyword is specified.
; If Image_Orig is 1D, then Lats and Lons must contain
; the same number of points.
; Lons- A vector or 2D array containing the longitude of each
; data point or column. If Lons is 1D, lon(image_orig(i,j)) =
; Lons(i); if Lons is 2D, lon(image_orig(i,j)) = Lons(i,j).
; This optional parameter may be omitted if the
; longitudes are equally spaced and are
; specified with the LON0 and LON1 keywords.
; Lats- A vector or 2D array containing the latitude of each
; data point or row If Lats is 1D, lat(image_orig(i,j))
; = Lats(j); if Lats is 2D, lat(image_orig(i,j)) =
; Lat(i,j). This optional parameter may be omitted
; if the latitudes are equally spaced and are specified
; with the LAT0 and LAT1 keywords.
;KEYWORDS:
; LAT0- The latitude of the first column of data. Default=-90.
; LAT1- The latitude of the last column of data. Default=+90.
; LON0- The longitude of the first row of data. Default=-180.
; LON1- The longitude of the last row of data. Default=180-360/Ny.
; MISSING = value to set areas outside the valid map coordinates.
; If omitted, areas outside the map are set to 255 (white) if
; the current graphics device is PostScript, or 0 otherwise.
; MAX_VALUE = values in Image_Orig greater than MAX_VALUE
; are considered missing. Pixels in the output image
; that depend upon missing pixels will be set to MISSING.
; TRIANGULATE = if set, the points are Delauny triangulated on
; the sphere using the TRIANGULATE procedure to determine
; connectivity. Otherwise, rectangular connectivity is assumed.
; Optional Output Keywords:
; xstart --- the x coordinate where the left edge of the image
; should be placed on the screen.
; ystart --- the y coordinate where th bottom edge of the image
; should be placed on the screen.
; xsize --- returns the width of the resulting image expressed in
; graphic coordinate units. If current graphics device has
; scalable pixels, the value of XSIZE and YSIZE should
; be passed to the TV procedure.
; ysize --- returns the pixel height of the resulting image, if the
; current graphics device has scalable pixels.
;
; Restrictions:
; This could be quicker.
; Output:
; The interpolated function/warped image is returned.
;
; Procedure:
; An object space algorithm is used, so the time required
; is roughly proportional to the size, in elements, of Image_Orig.
; Computations are performed in floating point.
; For rectangular grids, each rectangular cell of the original
; image is divided by a diagonal, into two triangles. If
; TRIANGULATE is set, indicating irregular gridding, the cells are
; triangulated. The trianges are then converted from lat/lon to
; image coordinates and then interpolated into
; the image array using TRIGRID.
;
;MODIFICATION HISTORY:
; DMS of RSI, July, 1994. Written.
; DMS, Nov, 1996. Rewritten and adapted for new maps, rev 2.
;-
ON_ERROR,2
if (!x.type NE 2) and (!x.type ne 3) THEN $ ;Need Mapping Coordinates
message, "Current window must have map coordinates"
s = size(Image_Orig)
Nx = s[1] ; # of columns
if s[0] eq 2 then Ny = s[2] else Ny = 1 ; # of rows
n = N_elements(Image_orig)
if n_elements(lons) eq 0 then begin ;Make longitudes?
if n_elements(lon0) le 0 then lon0 = -180.
if n_elements(lon1) le 0 then lon1 = 180. ;As documented
; if n_elements(lon1) le 0 then lon1 = lon0 - 360./nx + 360. ;as it was
dx = lon1-lon0
if dx le 0 then dx = dx + 360.
lons = findgen(nx) * (dx/(nx-1.)) + lon0
endif
if n_elements(lats) eq 0 then begin ;Make lats?
if n_elements(lat0) le 0 then lat0 = -90.
if n_elements(lat1) le 0 then lat1 = 90.
lats = findgen(ny) * ((lat1-lat0)/(ny-1.)) + lat0
endif
if n_elements(lats) ne ny and n_elements(lats) ne n then $
message, "Lats has incorrect size"
if n_elements(lons) ne nx and n_elements(lons) ne n then $
message, "Lons has incorrect size"
lonmin = min(lons, MAX=lonmax)
latmin = min(lats, MAX=latmax)
wrap = abs(map_reduce_360(lonmax + 360./nx-lonmin)) lt 1e-4
if wrap eq 0 then lnlim = [lonmin, lonmax] else lnlim = [-180., 180.]
ltlim = [latmin, latmax]
scale = !d.flags and 1 ;TRUE if device has scalable pixels
IF scale THEN BEGIN ;Fudge for postscript?
scalef = 0.02 ;PostScript scale factor
scale_orig = [!x.s, !y.s]
!x.s = !x.s * scalef
!y.s = !y.s * scalef
ENDIF ELSE scalef = 1
xw = scalef * !x.window ;Map extent in normalized coords
yw = scalef * !y.window
xw1 = !map.uv_box[[0,2]] * !x.s[1] + !x.s[0]
yw1 = !map.uv_box[[1,3]] * !y.s[1] + !y.s[0]
;Screen extent of our image in device coords
screen_x = long([ xw[0] > xw1[0], xw[1] < xw1[1] ] * !d.x_size)
screen_y = long([ yw[0] > yw1[0], yw[1] < yw1[1] ] * !d.y_size)
if n_elements(max_value) eq 0 then max_value = max(Image_orig)
if n_elements(missing) le 0 then missing = 0
rect = [screen_x[0], screen_y[0], screen_x[1], screen_y[1]]
if keyword_set(triangulate) then begin ;Make our own triangulation?
if n_elements(lons) eq n_elements(image_orig) then x = lons $
else if n_elements(lons) eq nx then x = lons # replicate(1., ny) $
else message, 'Dimension of LONS incompatible'
if n_elements(lats) eq n_elements(image_orig) then y = lats $
else if n_elements(lats) eq ny then y = replicate(1.,nx) # lats $
else message, 'Dimension of LATS incompatible'
temp = image_orig ;Copy cause TRIANGULATE, /SPHERE reorders data
triangulate, x, y, triangles, Sphere=s, /DEGREES, FVALUE=temp
x = trigrid(x, y, temporary(temp), triangles, [1., 1.], rect, $
MAX_VALUE=max_value, MISSING = missing, $
MAP=[!x.s * !d.x_size, !y.s * !d.y_size])
endif else begin ;Make a regular triangular grid
; Make 2D lat/lon arrays
if n_elements(lons) eq nx then x = lons # replicate(1., ny)
if n_elements(lats) eq ny then y = replicate(1.,nx) # lats
nr = nx - 1 + wrap ;If wrap, connect last row to first
do_north = abs(latmax-90.) lt 1.0e-3
do_south = abs(latmin+90.) lt 1.0e-3
; # of rows of triangles, 2 / row, except at poles.
nr1 = 2 * (ny-1) - do_north - do_south
i = (nx-1) * 6 ;Vertices / row
t = lonarr(nr * 6, /NOZERO) ;Typical row of rects
; Make our triangles in COUNTERCLOCKWISE order so they'll be properly clipped
; and split by the map routines.
for i=0, nr-1 do t[i*6] = ([i,i+1, i, i,i+1,i+1] mod nx) + $
[0, nx, nx, 0, 0, nx]
triangles = lonarr(nr1 * nr * 3, /NOZERO)
j = 0L
y0 = 0
if do_south then begin
for i=0, nr-1 do triangles[i*3] = ([i,i+1,i] mod nx) + [0, nx, nx]
j = 3*nr
y0 = 1
endif
if do_north then y1 = ny-3 else y1 = ny-2 ;Last row of rects
for iy= y0, y1 do begin
triangles[j] = t + iy * nx
j = j + 6*nr
endfor
if do_north then $ ;Top row
for i=0, nr-1 do triangles[j+i*3] = ([i, i+1, i] mod nx) + $
[0,0, nx] + nx*(ny-2)
; Interpolate from the triangular grid, in lat/lon onto an image bitmap.
x = trigrid(x, y, image_orig, triangles, [1., 1.], rect, $
MAX_VALUE=max_value, MISSING = missing, $
MAP=[!x.s * !d.x_size, !y.s * !d.y_size])
endelse ;triangular grid
xsize = ceil((rect[2] - rect[0])/scalef)
ysize = ceil((rect[3] - rect[1])/scalef)
xstart = long(rect[0] / scalef)
ystart = long(rect[1] / scalef)
if scale then begin ;Restore scale
!x.s = scale_orig[0:1] & !y.s = scale_orig[2:3]
endif
return, x
end